package tr.edu.ege.kipler.satisfiability.clash;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import tr.edu.ege.kipler.satisfiability.container.ABox;
import tr.edu.ege.kipler.satisfiability.container.ConceptCategory;
import tr.edu.ege.kipler.satisfiability.container.DependencyManager;
import tr.edu.ege.kipler.satisfiability.container.Individual;
import tr.edu.ege.kipler.satisfiability.container.RBox;
import tr.edu.ege.kipler.satisfiability.container.WorldConstraintSystem;
import tr.edu.ege.kipler.syntax.atomicformula.ConceptAssertion;
import tr.edu.ege.kipler.syntax.atomicformula.Formula;
import tr.edu.ege.kipler.syntax.concept.Concept;
import tr.edu.ege.kipler.syntax.concept.QualifiedNoRestriction;
import tr.edu.ege.kipler.syntax.concept.QualifiedNoRestriction.Constructor;

/**
 * 
 * @author İnanç Seylan
 *
 */
public class AtLeastAtMostClashDetectionStrategy implements
		ClashDetectionStrategy {

	private Set<WorldConstraintSystem> dependencySet = new HashSet<WorldConstraintSystem>();

	private ABox abox;

	public Set<WorldConstraintSystem> getDependencySet() {
		return dependencySet;
	}

	public boolean hasClash(ABox abox, Formula formula) {
		boolean result = false;
		this.abox = abox;
		if (formula instanceof ConceptAssertion) {
			ConceptAssertion ca = (ConceptAssertion) formula;
			if (ca.getConcept() instanceof QualifiedNoRestriction) {
				QualifiedNoRestriction qr = (QualifiedNoRestriction) ca
						.getConcept();
				Individual indv = abox.getIndividual(ca.getName());
				if (qr.getConstructor().equals(Constructor.AT_LEAST)) {
					result = atLeastViolated(qr, indv);
				} else {
					result = atMostViolated(qr, indv);
				}
			}
		}
		return result;
	}

	private boolean atLeastViolated(QualifiedNoRestriction atLeast,
			Individual indv) {
		boolean violated = false;
		Iterator<Concept> i = indv.conceptIterator(ConceptCategory.AT_MOST);
		while (i.hasNext() && !violated) {
			QualifiedNoRestriction atMost = (QualifiedNoRestriction) i.next();
			if (minMaxViolated(indv, atMost, atLeast)) {
				violated = true;
			}
		}
		return violated;
	}

	private boolean atMostViolated(QualifiedNoRestriction atMost,
			Individual indv) {
		boolean violated = false;
		Iterator<Concept> i = indv.conceptIterator(ConceptCategory.AT_LEAST);
		while (i.hasNext() && !violated) {
			QualifiedNoRestriction atLeast = (QualifiedNoRestriction) i.next();
			if (minMaxViolated(indv, atMost, atLeast)) {
				violated = true;
			}
		}
		return violated;
	}

	private boolean minMaxViolated(Individual indv,
			QualifiedNoRestriction atMost, QualifiedNoRestriction atLeast) {
		boolean violated = false;
		RBox rbox = abox.getWorld().getRBox();
		if (atMost.getNo() < atLeast.getNo()
				&& atMost.getConcept().equals(atLeast.getConcept())
				&& rbox.getSubRoles(atMost.getRole()).contains(
						atLeast.getRole())) {
			violated = true;
			DependencyManager depMan = abox.getWorld().getWcs().getData()
					.getDependencyManager();
			getDependencySet().clear();
			getDependencySet().addAll(
					depMan.getDependencies(new ConceptAssertion(atMost, indv
							.getName())));
			getDependencySet().addAll(
					depMan.getDependencies(new ConceptAssertion(atLeast, indv
							.getName())));
		}
		return violated;
	}

	public String getExplanation() {
		return "QR";
	}

}
